package com.ctshk.common.log.aspect;

import com.alibaba.fastjson.JSONObject;
import com.ctshk.common.annotations.SearchHotWord;
import com.ctshk.common.constant.RedisConstants;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.log.entity.CommodityHotWord;
import com.ctshk.common.log.mapper.CommodityHotWordMapper;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.RSAUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * @author 黄利斌
 * @description 操作搜索热词记录操作类
 * @date 2021/5/25 4:06 下午
 */
@Slf4j
@Aspect
@Component
public class SearchHotWordAspect {

    @Resource
    private CommodityHotWordMapper commodityHotWordMapper;

    @Resource
    public void setCommodityHotWordMapper(CommodityHotWordMapper commodityHotWordMapper) {
        this.commodityHotWordMapper = commodityHotWordMapper;
    }

    /**
     * 设置操作日志切入点   在注解的位置切入代码
     */
    @Pointcut("@annotation(com.ctshk.common.annotations.SearchHotWord)")
    public void operSearchHotWordPoinCut() {
    }

    /**
     * 在切点之前织入
     *
     * @param joinPoint
     * @throws Throwable
     */
    @Before("operSearchHotWordPoinCut()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 打印请求相关参数
        log.info("========================================== AOP Search Start ==========================================");
    }

    /**
     * 在切点之后织入
     *
     * @throws Throwable
     */
    @After("operSearchHotWordPoinCut()")
    public void doAfter() throws Throwable {
        // 接口结束后换行，方便分割查看
        log.info("=========================================== AOP Search End ===========================================");
    }

    /**
     * 保存操作词汇,正常返回
     *
     * @param joinPoint 方法的执行点
     * @param result    方法返回值
     * @throws Throwable
     */
    @AfterReturning(returning = "result", value = "operSearchHotWordPoinCut()")
    public void saveOperLog(JoinPoint joinPoint, Object result) {
        // 获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        try {

            // 从切面织入点处通过反射机制获取织入点处的方法
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            // 获取切入点所在的方法
            Method method = signature.getMethod();

            CommodityHotWord commodityHotWord = null;
            // 获取操作
            SearchHotWord searchHotWord = method.getAnnotation(SearchHotWord.class);
            if (searchHotWord != null) {
                Object[] args = joinPoint.getArgs();
                for (Object arg : args) {
                    if (arg instanceof String) {
                        commodityHotWord = commodityHotWordMapper.selectByWord(arg.toString());
                            // 新增
                        if (null == commodityHotWord) {
                            commodityHotWord = new CommodityHotWord();
                            commodityHotWord.setWords(arg.toString());
                            String token = request.getHeader(RedisConstants.JWT_TOKEN_HEADER);
                            if (StringUtils.isNotBlank(token)) {
                                TokenUser tokenUser = new TokenUser();
                                try {
                                    token = token.replace(RedisConstants.JWT_TOKEN_PREFIX, Strings.EMPTY);
                                    String tokenDecrypt = RSAUtil.decryptStr(token);
                                    tokenUser = JSONObject.parseObject(tokenDecrypt, TokenUser.class);
                                } catch (Exception e) {
                                    throw new BusinessException(SystemError.USER_1015);
                                }
                                Long userId = tokenUser.getId();
                                commodityHotWord.setCreateId(userId);
                            }
                            if (null == commodityHotWord.getNumber()) {
                                commodityHotWord.setNumber(1L);
                            }
                            commodityHotWord.setId(SnowflakeIdWorker.nextId());
                            commodityHotWord.setIsDeleted(0);
                            commodityHotWord.setGmtCreate(LocalDateTime.now());
                            commodityHotWord.setGmtModified(LocalDateTime.now());
                            commodityHotWordMapper.saveEntity(commodityHotWord);
                        }else {
                            // 修改
                            commodityHotWord.setNumber(commodityHotWord.getNumber()+1);
                            commodityHotWordMapper.updateById(commodityHotWord);
                        }
                    }
                }
            }
            log.info("保存词汇成功：[{}]", commodityHotWord);
        } catch (Exception e) {
            // e.printStackTrace();
            log.info("搜索词汇写入失败：{}", e.getMessage());
        }
    }
}
